#pragma once
#include<iostream>
#include<queue>
#include<pthread.h>
#include"LockGuard.hpp"

const int defaultcap=5;//默认容量为5
template<class T>
class block_queue
{
private:
    std::queue<T> _q;
    int _capacity;   //_q.size() == _capacity, 满了，不能在生产，_q.size() == 0, 空，不能消费了
    pthread_mutex_t _mutex;
    pthread_cond_t _push_cond;  //给生产者
    pthread_cond_t _pop_cond;  //给消费者
    // int _consumer_water_line;  // _consumer_water_line = _capacity / 3 * 2
    // int _productor_water_line; // _productor_water_line = _capacity / 3
public:
    block_queue(int cap=defaultcap)
    :_capacity(cap)
    {
        pthread_mutex_init(&_mutex,nullptr);
        pthread_cond_init(&_push_cond,nullptr);
        pthread_cond_init(&_pop_cond,nullptr);
    }
     bool IsFull()
    {
        return _q.size() == _capacity;
    }
    bool IsEmpty()
    {
        return _q.size() == 0;
    }
    void Push(const T &in)
    {
        LockGuard lockguard(&_mutex);
        while(IsFull())
        pthread_cond_wait(&_push_cond,&_mutex);

        _q.push(in);
        //通知消费者可以消费了
         // if(_q.size() > _productor_water_line) pthread_cond_signal(&_c_cond);  // 也可以是当资源数量大于指定阈值时再通知
        pthread_cond_signal(&_pop_cond);
        
    }

    void Pop(T *out)//要取出任务
    {
        LockGuard lockgugrd(&_mutex);
        while(IsEmpty())
        pthread_cond_wait(&_pop_cond,&_mutex);

        *out=_q.front();
        _q.pop();
        //通知生产者可以生产了
        // if(_q.size() < _consumer_water_line) pthread_cond_signal(&_p_cond);      //也可以是当资源数量大于指定阈值时再通知
        pthread_cond_signal(&_push_cond);
    }
    ~block_queue()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_push_cond);
        pthread_cond_destroy(&_pop_cond);
    }

};

